﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using ClientTools.Library.DataTypes.Umbraco;
using ClientTools.Library.DataTypes.Versions;
using ClientTools.Library.Interfaces;
using Version=ClientTools.Library.DataTypes.Versions.Version;

namespace ClientTools.Client.Controls.Versions
{
    public partial class UcVersionsTree : UserControl
    {
        private IVersions actVersions;
        private INodes actNodes;

        public UcVersionsTree()
        {
            InitializeComponent();
            Client.Controls.GridViewHelper.SetGridLayout(dataGridView1);
        }

        public void SetData(IVersions iVersions, INodes iNodes)
        {
            actVersions = iVersions;
            actNodes = iNodes;

            ClearData();
            Enabled = true;
        }

        public void ClearData()
        {
            treeView1.Nodes.Clear();
            dataGridView1.DataSource = null;
        }

        private void tsbGetRootNodes_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            treeView1.SuspendLayout();

            treeView1.Nodes.Clear();
            foreach (var item in actNodes.GetNodes(-1, false))
            {
                var vi = actVersions.GetVersionInfos(item.Id);
                treeView1.Nodes.Add(new TreeNode(string.Format("{0} ({1})", item.Name, vi.Versions)) {Tag = item, ImageIndex = 0, SelectedImageIndex = 1});
            }

            treeView1.ResumeLayout();
            Cursor = Cursors.Default;
        }

        private void tsbDeleteSelectedVersions_Click(object sender, EventArgs e)
        {
            DeleteVersions();
        }

        //private static void UpdateNodeInfos(TreeNode treeNode, int value)
        //{
        //    var node = (Node)treeNode.Tag;
        //    //node.ChildrenVersionCount -= value;
        //    if (treeNode.Parent != null)
        //        UpdateNodeInfos(treeNode.Parent, value);
        //}

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            var node = (Node)e.Node.Tag;
            if (node.ChildrenLoaded == false)
                LoadNodes(e.Node);
            ShowDetails(node);
            Cursor = Cursors.Default;
        }

        private void ShowDetails(Node node)
        {
            VersionInfo nodeInfos = actVersions.GetVersionInfos(node.Id);
            VersionInfo childrenInfos = actVersions.GetChildrenVersionInfos(node.Id);

            lblNodeVersions.Text = string.Format("- {0} versions(s)", nodeInfos.Versions);
            lblNodePropertyData.Text = string.Format("- {0} property data(s)", nodeInfos.PropertyData);
            lblChildNodesDocuments.Text = string.Format("- {0} published document(s)", childrenInfos.Documents);
            lblChildNodesVersions.Text = string.Format("- {0} versions(s)", childrenInfos.Versions);
            lblChildNodesPropertyDatas.Text = string.Format("- {0} property data(s)", childrenInfos.PropertyData);

            dataGridView1.DataSource = actVersions.GetVersions(node.Id);
// ReSharper disable PossibleNullReferenceException
            dataGridView1.Columns["UpdateDate"].DefaultCellStyle.Format = "dd.MM.yyyy HH:mm:ss";
            dataGridView1.Columns["VersionDate"].DefaultCellStyle.Format = "dd.MM.yyyy HH:mm:ss";
// ReSharper restore PossibleNullReferenceException
        }

        private void LoadNodes(TreeNode tn)
        {
            var node = (Node)tn.Tag;
            treeView1.SuspendLayout();

            foreach (var item in actVersions.GetNodes(node.Id, false))
            {
                node.Children.Add(item);
                var vi = actVersions.GetVersionInfos(item.Id, false);
                tn.Nodes.Add(new TreeNode(string.Format("{0} ({1})", item.Name, vi.Versions)) { Tag = item, ImageIndex = 0, SelectedImageIndex = 1 });
            }
            tn.Expand();

            treeView1.ResumeLayout();
        }

        private void tsbDeleteVersionsByDate_Click(object sender, EventArgs e)
        {
            var dlgDeleteByDate = new DlgDeleteByDate();
            if (dlgDeleteByDate.ShowDialog() != DialogResult.OK) 
                return;
            
            Cursor = Cursors.WaitCursor;

            var date = dlgDeleteByDate.CutOffTime;
            var recursive = dlgDeleteByDate.Recursive;

            DeleteVersionsByDate(treeView1.SelectedNode, date, recursive);

            Cursor = Cursors.Default;
            MessageBox.Show("Done");
        }

        private void DeleteVersionsByDate(TreeNode treeNode, DateTime date, bool recursive)
        {
            var node = (Node)treeNode.Tag;
            actVersions.DeleteVersionsByDate(date, node.Id);
            
            if (!recursive) 
                return;

            if (!node.ChildrenLoaded)
                LoadNodes(treeNode);
            foreach (TreeNode item in treeNode.Nodes)
                DeleteVersionsByDate(item, date, true);
        }

        private void DeleteVersions()
        {
            if (dataGridView1.SelectedRows.Count == 0)
            {
                MessageBox.Show("No row (version) selected", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            var guids = new List<Guid>();
            foreach (DataGridViewRow item in dataGridView1.SelectedRows)
            {
                var v = (Version)item.DataBoundItem;
                if (v.IsNewest || v.Published)
                {
                    MessageBox.Show("You cannot delete published or newest versions", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                guids.Add(v.Guid);
            }
            
            if (MessageBox.Show("Are you sure that you want to delete the selected versions?", "Security question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) 
                return;

            Cursor = Cursors.WaitCursor;
            var node = (Node)treeView1.SelectedNode.Tag;

            var deleteInfos = new VersionInfo();
            var i = 0;
            foreach (var item in guids)
            {
                var di = actVersions.DeleteVersion(item);
                deleteInfos.Documents += di.Documents;
                deleteInfos.PropertyData += di.PropertyData;
                deleteInfos.Versions += di.Versions;
                i++;
            }
            treeView1.SelectedNode.Text = string.Format("{0} ({1})", node.Name, actVersions.GetVersionInfos(node.Id).Versions);
            //UpdateNodeInfos(treeView1.SelectedNode, i);
            ShowDetails(node);
            Cursor = Cursors.Default;
            MessageBox.Show(string.Format("{0} version(s) with {1} property datas deleted", i, deleteInfos.PropertyData), "Ready", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void TsbDeleteVersionsByNumberOfItems_Click(object sender, EventArgs e)
        {
            var dlgDeleteByNumberOfItems = new DlgDeleteByNumberOfItems();
            if (dlgDeleteByNumberOfItems.ShowDialog() != DialogResult.OK)
                return;

            Cursor = Cursors.WaitCursor;

            var numberOfItems = dlgDeleteByNumberOfItems.NumberOfItems;
            var recursive = dlgDeleteByNumberOfItems.Recursive;

            DeleteVersionsByNumberOfItems(treeView1.SelectedNode, numberOfItems, recursive);

            Cursor = Cursors.Default;
            MessageBox.Show("Done");
        }

        private void DeleteVersionsByNumberOfItems(TreeNode treeNode, int numberOfItems, bool recursive)
        {
            var node = (Node)treeNode.Tag;
            actVersions.DeleteVersionsByItems(numberOfItems, node.Id);
            
            if (!recursive) 
                return;

            if (!node.ChildrenLoaded)
                LoadNodes(treeNode);
            foreach (TreeNode item in treeNode.Nodes)
                DeleteVersionsByNumberOfItems(item, numberOfItems, true);
        }

    }
}
